package com.chuangjiangx.member.stored.ddd.domain.stardard;

import com.chuangjiangx.commons.JacksonUtils;
import com.chuangjiangx.commons.SpringContext;
import com.chuangjiangx.member.basic.ddd.domain.model.MbrAccount;
import com.chuangjiangx.member.basic.ddd.domain.model.Member;
import com.chuangjiangx.member.basic.ddd.domain.model.calc.AmountScoreGrandTotalCalc;
import com.chuangjiangx.member.stored.ddd.domain.AbstractMbrRefund;
import com.chuangjiangx.member.stored.ddd.domain.MbrPaymentConstant;
import com.chuangjiangx.member.score.ddd.domain.model.MbrScoreStream;
import com.chuangjiangx.member.stored.ddd.domain.event.MbrRefundSuccessEvent;
import com.chuangjiangx.member.score.ddd.domain.model.MbrScoreType;
import com.chuangjiangx.member.stored.ddd.domain.model.MbrStoredType;
import com.chuangjiangx.member.stored.ddd.domain.model.*;
import com.chuangjiangx.member.common.utils.MbrKeyManager;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;


/**
 * @author cj-ch
 * @date 2018/4/6 下午1:10
 */
public class StandardMbrRefund extends AbstractMbrRefund {
    protected static volatile Boolean inited = false;
    private static MbrOrderRepository mbrOrderRepository;
    private static MbrOrderRefundRepository mbrOrderRefundRepository;

    private static  RedisTemplate redisTemplate;
    private static  ObjectMapper objectMapper;

    public StandardMbrRefund(MbrRefundContext context) {
        super(context);
        andAfterRefund(refundAfter());
        init();
    }

    private void init(){
        if(!inited){
            synchronized (StandardMbrPayment.class){
                if(!inited){
                    mbrOrderRepository = SpringContext.getBean(MbrOrderRepository.class);
                    mbrOrderRefundRepository = SpringContext.getBean(MbrOrderRefundRepository.class);
                    redisTemplate = SpringContext.getBean("redisTemplate");
                    objectMapper = SpringContext.getBean("objectMapper");
                    inited = true;
                }
            }
        }
    }


    @Override
    protected MbrRefundDomainResult doRefund() {
        MbrRefundDomainResult result = new MbrRefundDomainResult();
        MbrOrder order = context.getMbrOrder();
        MbrOrderRefund refund = context.getMbrOrderRefund();
        Member member = context.getMember();
        MbrAccount account = context.getMbrAccount();
        order.refund(refund);
        //账户变动
        account.changeMoney(refund.getRefundAmount(),MbrStoredType.REFUND);
        MbrScoreStream scoreStreamHis = context.getMbrScoreStreamHis();
        if(null != scoreStreamHis){
            //计算扣除积分
            if(0 < scoreStreamHis.getScore()){
                Long deductinScore = new AmountScoreGrandTotalCalc()
                        .subtractScoreCalc(refund.getRefundAmount(), order.getPaidAmount(), scoreStreamHis.getScore());
                account.changeScore(deductinScore,MbrScoreType.REFUND);
                result.setDeductionScore(deductinScore.intValue());
            }
        }

        result.setResultCode(MbrPaymentConstant.SUCCESS);
        result.setAmount(refund.getRefundAmount());
        result.setTotalAmount(order.getRefundAmount());
        result.setRefundTime(new Date());
        result.setRefundType(order.getPayEntry().value);
        result.setRefundTerminal(refund.getTerminal().code);
        result.setPayType(order.getPayEntry().value);
        result.setPayStatus(order.getStatus().value);
        result.setMemberMobile(member.getMobile());
        result.setAvailableBalance(account.getAvailableBalance());
        result.setAvailableScore(account.getAvailableScore());
        //保存数据
        mbrOrderRepository.update(order);
        mbrOrderRefundRepository.save(refund);

        //把退款订单存储到redis,5分钟
        MbrOrderRefundMirror mbrOrderRefundMirror = MbrOrderRefundMirror.of(refund);
        redisTemplate.opsForValue()
                .set(
                        MbrKeyManager.MBR_ORDER_REFUND_ID_KEY+mbrOrderRefundMirror.getId(),
                        JacksonUtils.toJson(objectMapper,mbrOrderRefundMirror),
                        5,TimeUnit.MINUTES);
        return result;
    }

    /**
     * 退款后
     * @return
     */
    private BiConsumer<MbrRefundContext, MbrRefundDomainResult> refundAfter(){
        return (context,result) -> {
            MbrOrder order = context.getMbrOrder();
            MbrOrderRefund refund = context.getMbrOrderRefund();
            MbrAccount account = context.getMbrAccount();
            MbrRefundSuccessEvent event = new MbrRefundSuccessEvent.MbrRefundSuccessEventBuild()
                    .setCurrentRefundAmout(refund.getRefundAmount())
                    .setRealPayAmount(order.getPaidAmount())
                    .setTotalRefundAmout(order.getRefundAmount())
                    .setMbrOrderId(order.getId().getId())
                    .setMbrOrderRefundId(refund.getId().getId())
                    .setPayChannelId(15)
                    .setPayEntry(order.getPayEntry())
                    .setPayType(order.getPayType())
                    .setPayTerminal(order.getPayTerminal())
                    .setMemberId(account.getMemberId().getId())
                    .setMerchantId(refund.getMerchantId().getId())
                    .setMerchantUserId(refund.getMerchantUserId())
                    .setStoreId(refund.getStoreId())
                    .setStoreUserId(refund.getStoreUserId())

                    .setMerchantAddress(context.getMerchantAddress())
                    .setStoreAddress(context.getStoreAddress())
                    .build();

            redisTemplate.convertAndSend("mbr_refund_success",JacksonUtils.toJson(objectMapper,event));

        };
    }


}
